package com.scwatch.core.fulltext;


import com.scwatch.common.fulltext.LuceneException;
import com.scwatch.core.domain.Node;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.springframework.util.NumberUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.apache.lucene.document.Field.Index.ANALYZED;
import static org.apache.lucene.document.Field.Index.NOT_ANALYZED;
import static org.apache.lucene.document.Field.Store.NO;
import static org.apache.lucene.document.Field.Store.YES;
import static org.apache.lucene.search.BooleanClause.Occur.*;
import static org.apache.lucene.util.Version.LUCENE_36;


/**
 * 栏目实体的全文检索转换类
 *
 */
public class FNode {
	public static final String ID = "id";
	public static final String SITE_ID = "siteId";
	public static final String PARENT_ID = "parentId";
	public static final String NAME = "name";
	public static final String DESCRIPTION = "description";
	public static final String TREENUMBER = "treeNumber";
	public static final String CITY="CITY";

	public static List<Integer> idsFromDoc(List<Document> docList) {
		if (!docList.isEmpty()) {
			List<Integer> ids = new ArrayList<Integer>(docList.size());
			for (Document doc : docList) {
				ids.add(NumberUtils.parseNumber(doc.get(ID), Integer.class));
			}
			return ids;
		} else {
			return Collections.emptyList();
		}
	}

	public static List<Integer> idsFromString(List<String> idList) {
		if (!idList.isEmpty()) {
			List<Integer> ids = new ArrayList<Integer>(idList.size());
			for (String id : idList) {
				ids.add(NumberUtils.parseNumber(id, Integer.class));
			}
			return ids;
		} else {
			return Collections.emptyList();
		}
	}

	public static Term id(Integer id) {
		return new Term(FNode.ID, String.valueOf(id));
	}

	public static Document doc(Node node) {
	    if(node==null){
	        return null;
        }
		Document doc = new Document();
		String id = String.valueOf(node.getId());
		doc.add(new Field(ID, id, YES, NOT_ANALYZED));

		String siteId = String.valueOf(node.getSite().getId());
		doc.add(new Field(SITE_ID, siteId, NO, NOT_ANALYZED));

		if (node != null && node.getParent()!=null) {
			String parentId = String.valueOf(node.getParent().getId());
			doc.add(new Field(PARENT_ID, parentId, NO, NOT_ANALYZED));
		}

		String name =node.getName();
		if (StringUtils.isNotBlank(name)) {
			doc.add(new Field(NAME, name, YES, ANALYZED));
		}

		String description = node.getMetaDescription();
		if (StringUtils.isNotBlank(description)) {
			doc.add(new Field(DESCRIPTION, description, NO, ANALYZED));
		}

        String treeNumber =node.getTreeNumber();
        if (StringUtils.isNotBlank(treeNumber)) {
            doc.add(new Field(TREENUMBER, treeNumber, NO, NOT_ANALYZED));
        }

        String city=node.getCity();
        NumericField cityField = new NumericField(city);
        if(StringUtils.isNotBlank(city)){
            if(Node.ANCHOR_CITY.equals(city)){
                doc.add(cityField.setIntValue(0));
            }else{
                doc.add(cityField.setIntValue(1));
            }
        }else{
            doc.add(cityField.setIntValue(1));
        }

		return doc;
	}

	public static Query query(Analyzer analyzer, Integer[] siteIds,
			Integer[] parentIds, Integer[] excludeId,
            String name,String description) {
        try {
            BooleanQuery query = new BooleanQuery();
            if (ArrayUtils.isNotEmpty(siteIds)) {
                BooleanQuery qy = new BooleanQuery();
                for (Integer id : siteIds) {
                    String s = String.valueOf(id);
                    qy.add(new TermQuery(new Term(SITE_ID, s)), SHOULD);
                }
                query.add(qy, MUST);
            }
            if (ArrayUtils.isNotEmpty(parentIds)) {
                BooleanQuery qy = new BooleanQuery();
                for (Integer id : parentIds) {
                    String s = String.valueOf(id);
                    qy.add(new TermQuery(new Term(PARENT_ID, s)), SHOULD);
                }
                query.add(qy, MUST);
            }

            if (ArrayUtils.isNotEmpty(excludeId)) {
                for (Integer id : excludeId) {
                    query.add(new TermQuery(id(id)), MUST_NOT);
                }
            }

            BooleanQuery booleanQuery= new BooleanQuery();
            if (StringUtils.isNotBlank(name)) {
                name = QueryParser.escape(name);
                QueryParser p = new QueryParser(LUCENE_36, NAME, analyzer);
//                query.add(p.parse(name), MUST);
                booleanQuery.add(p.parse(name), BooleanClause.Occur.SHOULD);
            }

            if (StringUtils.isNotBlank(description)) {
                description = QueryParser.escape(description);
                QueryParser p = new QueryParser(LUCENE_36, DESCRIPTION,
                        analyzer);
//                query.add(p.parse(description), MUST);
                booleanQuery.add(p.parse(description), BooleanClause.Occur.SHOULD);
            }
            query.add(booleanQuery,BooleanClause.Occur.MUST);

            return query;
        } catch (Exception e) {
            throw new LuceneException("Error during create query.", e);
        }
	}


}
